package org.zqh.mvc;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.zqh.mvc.annotation.ZqhAction;
import org.zqh.mvc.annotation.ZqhForm;
import org.zqh.mvc.annotation.ZqhResult;
import org.zqh.mvc.annotation.ZqhResults;

/**
 * 监听器，在初始化时读取mvc的配置文件
 * 
 * 项目名称：zqhmvc 类名称：ActionListener 类描述： 创建人：zhangqh 创建时间：2015年5月21日 下午11:03:41
 * 修改人：zhangqh 修改时间：2015年5月21日 下午11:03:41 修改备注：
 * 
 * @version
 * 
 */
public class ActionListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		System.out.println("监听器注销");
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		System.out.println("监听器启动");
		ServletContext context = arg0.getServletContext();
		try {
			// context.setAttribute("zqhmvc", parseXml(context.getRealPath("\\")
			// + context.getInitParameter("zqhmvc-config")));

			// 改为Annotation模式
			context.setAttribute("zqhmvc",
					parseAnnotation(context.getInitParameter("basePackage")));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 解析mvc的xml配置文件
	 * 
	 * @param mvcConfigFile
	 * @return
	 * @throws Exception
	 */
	private Map<String, ActionMapping> parseXml(String mvcConfigFile)
			throws Exception {
		Map<String, ActionMapping> map = new HashMap<String, ActionMapping>();
		// 引用jdom的SAXBuilder解析
		SAXBuilder sax = new SAXBuilder();
		Document document = sax.build(mvcConfigFile);
		Element rootElement = document.getRootElement();

		Element eFormBeans = rootElement.getChild("form-beans");
		Element eActionMapping = rootElement.getChild("action-mappings");

		List<Element> listAction = eActionMapping.getChildren();
		for (Element eAction : listAction) {
			ActionMapping mxc = new ActionMapping();
			mxc.setName(eAction.getAttributeValue("name"));
			mxc.setPath(eAction.getAttributeValue("path"));
			mxc.setType(eAction.getAttributeValue("type"));

			Map<String, String> mapForward = new HashMap<String, String>();
			List<Element> listForward = eAction.getChildren();
			for (Element eForward : listForward) {
				mapForward.put(eForward.getAttributeValue("name"),
						eForward.getAttributeValue("path"));
			}
			mxc.setActionForward(mapForward);

			List<Element> listFormBean = eFormBeans.getChildren();
			for (Element eForm : listFormBean) {
				if (mxc.getName().equals(eForm.getAttributeValue("name"))) {
					mxc.setName(eForm.getAttributeValue("type"));
					break;
				}
			}
			map.put(mxc.getPath(), mxc);
		}

		return map;
	}

	@SuppressWarnings("unchecked")
	public Map<String, ActionMapping> parseAnnotation(String basePackage)
			throws Exception {
		List<String> classNames = new ArrayList<String>();
		String filePath = this.getClass().getClassLoader()
				.getResource(basePackage.replaceAll("\\.", "/")).getFile();
		List<String> names = Arrays.asList(new File(filePath).list());

		for (String name : names) {
			classNames.add(basePackage + "." + name.replace(".class", ""));
		}
		Map<String, ActionMapping> map = new HashMap<String, ActionMapping>();
		for (int i = 0; i < classNames.size(); i++) {
			ActionMapping am = new ActionMapping();
			String className = classNames.get(i);
			Class clz = Class.forName(className);
			String actionPath = "";
			if (clz.isAnnotationPresent(ZqhAction.class)) {
				ZqhAction action = (ZqhAction) clz
						.getAnnotation(ZqhAction.class);
				actionPath = action.path();
				am.setPath(actionPath);
				am.setType(className);

				Map<String, String> actionForward = new HashMap<String, String>();
				if (clz.isAnnotationPresent(ZqhResults.class)) {
					ZqhResults zqhResultsAnnotition = (ZqhResults) clz
							.getAnnotation(ZqhResults.class);
					ZqhResult[] zqhResults = zqhResultsAnnotition.zqhResults();
					for (int j = 0; j < zqhResults.length; j++) {
						ZqhResult zr = zqhResults[j];
						String forwardPath = zr.path();
						String forwardName = zr.name();
						actionForward.put(forwardName, forwardPath);
					}
				}
				am.setActionForward(actionForward);
				if (clz.isAnnotationPresent(ZqhForm.class)) {
					ZqhForm form = (ZqhForm) clz.getAnnotation(ZqhForm.class);
					am.setName(form.type());
				}
				map.put(actionPath, am);
			}

		}
		return map;
	}
}
